package state

import (
	"fmt"
	"luu/binchunk"
)

func (this *luaState) GetTop() int {
	return this.stack.top
}

func (this *luaState) AbsIndex(idx int) int {
	return this.stack.absIndex(idx)
}
func (this *luaState) CheckStack(n int) bool {
	this.stack.check(n)
	return true
}
func (this *luaState) Pop(n int) {
	this.SetTop(-n - 1)
}

func (this *luaState) Copy(fromIdx, toIdx int) {
	this.stack.set(toIdx, this.stack.get(fromIdx))
}
func (this *luaState) PushValue(idx int) {
	val := this.stack.get(idx)
	this.stack.push(val)
}
func (this *luaState) Replace(idx int) {
	val := this.stack.pop()
	this.stack.set(idx, val)
}

func (this *luaState) Insert(idx int) {
	this.Rotate(idx, 1)
}

func (this *luaState) Remove(idx int) {
	this.Rotate(idx, -1)
	this.Pop(1)
}
func (this *luaState) Rotate(idx, n int) {
	t := this.stack.top - 1
	p := this.stack.absIndex(idx) - 1
	var m int
	if n >= 0 {
		m = t - n
	} else {
		m = p - n - 1
	}
	this.stack.reverse(p, m)
	this.stack.reverse(m+1, t)
	this.stack.reverse(p, t)
}

/**
设置栈顶的索引
*/
func (this *luaState) SetTop(idx int) {
	newTop := this.stack.absIndex(idx)
	if newTop < 0 {
		panic("setTop error,idx invalid")
	}
	if newTop < this.stack.top {
		this.stack.top = newTop
	} else if newTop > this.stack.top {
		this.stack.check(newTop)
		this.stack.top = newTop
	}
}
func (this *luaState) PushNil() {
	this.stack.push(nil)
}
func (this *luaState) PushBoolean(b bool) {
	this.stack.push(b)
}

func (this *luaState) PushInteger(n int64) {
	this.stack.push(n)
}

func (this *luaState) PushNumber(n float64) {
	this.stack.push(n)
}
func (this *luaState) PushString(s string) {
	this.stack.push(s)
}
func (this *luaState) PrintStack() {
	str := ""
	for i := 1; i <= this.stack.top; i++ {
		str += "[" + this.PeekStack(i) + "] "
		if i == this.RegisterCount() {
			str += " __ " //碰到了 registercount
		}
	}
	fmt.Println(str)
}

func (this *luaState) Peek(n int) luaValue {
	return this.stack.get(n)
}

func (this *luaState) PushLuaStack(stack *LuaStack) {
	stack.prev = this.stack
	this.stack = stack
}

func (this *luaState) PopLuaStack() {
	oldStack := this.stack
	this.stack = oldStack.prev
	oldStack.prev = nil
}

func (this *luaState) Load(chunk []byte, chunkName, mode string) int {
	proto := binchunk.Undump(chunk)
	c := NewLuaClosure(proto)
	this.stack.push(c)
	if len(proto.UpValues) > 0 {
		env := this.registry.Get(LUA_RIDX_GLOBALS)
		c.upvalues[0] = &upvalue{&env}
	}
	return 0
}

func (this *LuaStack) PushN(vs []luaValue, n int) {
	if n < 0 {
		n = len(vs)
	}
	for i := 0; i < n; i++ {
		if i < len(vs) {
			this.push(vs[i])
		} else {
			this.push(nil)
		}
	}
}

func (this *LuaStack) PopN(n int) []luaValue {
	res := make([]luaValue, n)
	for i := n - 1; i >= 0; i-- {
		res[i] = this.pop()
	}
	return res
}
